package control.manager
{
	//import control.util.AStarPathFinder;
	import control.util.astar.AStarStaggered;
	import control.util.astar.Node;
	import control.util.astar.NodeGrid;
	import control.util.bfs.BFS;
	
	import data.ExitsData;
	import data.GameConst;
	import data.MapData;
	import data.MonsterData;
	import data.NPCData;
	
	import flash.events.Event;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import view.item.ExitsView;
	import view.layer.GameLayer;
	import view.role.MapPlayer;
	

	/**
	 * 地图数据管理 
	 * @author leo
	 * 
	 */	
	public class MapManager
	{
		private static var _instance :MapManager = null;
		/**
		 * 所有地图信息列表 
		 */		
		public var mapDataList :Vector.<MapData>;
		/**
		 * 当前玩家所在地图的地图信息 
		 */		
		public var curMapData :MapData;
		/**
		 * Staggered 寻路算法 
		 */		
		public var astar :AStarStaggered;
		/**
		 * 寻路用的节点数据 
		 */		
		public var nodeGrid :NodeGrid;
		/**
		 * 所有地图的传送点信息 
		 */		
		public var allExitDataList :Array;
		
		public function MapManager(prvClass :PrivateClass)
		{
			this.mapDataList = new Vector.<MapData>();
			this.astar = new AStarStaggered();
			allExitDataList = [];
		}

		public static function get instance():MapManager
		{
			if(_instance == null)
			{
				_instance = new MapManager(new PrivateClass());
			}
			return _instance;
		}
		
		/**
		 * 寻路 
		 * @param startPoint 起点
		 * @param endPoint 终点
		 * @return 
		 * 
		 */		
		public function findPath(startPoint :Point,endPoint :Point):Array
		{
			var found:Boolean = astar.findPath(this.nodeGrid,startPoint.x,startPoint.y,endPoint.x,endPoint.y);
			if ( found ) 
			{
				var path:Array = astar.path;
				var pointPath:Array = new Array();
				for(var index : uint = 0;index < path.length; index++) 
				{
					var node:Node = path[index];
					pointPath.push(new Point(node.tx,node.ty));
				}
				return pointPath;
			}
			return null;
		}
		/**
		 * 初始化寻路节点信息 
		 * @param mapData
		 * 
		 */		
		public function initNodeGrid(mapData :MapData):void
		{
			this.nodeGrid = this.ary2WalkGrid(mapData.mapWalkAry);
		}
		
		/**
		 * 根据地图id查找地图数据 ，会将MapManager中的当前地图数据自动切换找到的地图数据
		 * @param mapID
		 * @return 
		 * 
		 */		
		public function findByID(mapID :int):MapData
		{
			var item :MapData;
			for each(var mapData :MapData in this.mapDataList)
			{
				if(mapData.mapID == mapID)
				{
					item = mapData;
					this.curMapData = mapData;
				}
			}
			return item;
		}
		/**
		 * 根据像素坐标得到直角坐标	
		 * */
		public  function getDirectPointByPixel(tileWidth:int, tileHeight:int, px:int, py:int,row:int):Point
		{
			return getDirectPoint(getCellPoint(tileWidth,tileHeight,px,py),row);
		}
		
		/**
		 *  根据屏幕象素坐标取得网格的坐标
		 * @param tileWidth
		 * @param tileHeight
		 * @param px
		 * @param py
		 * @return 
		 * 
		 */		
		public  function getCellPoint(tileWidth:int, tileHeight:int, px:int, py:int):Point
		{
			var xtile:int = 0;	//网格的x坐标
			var ytile:int = 0;	//网格的y坐标
			
			var cx:int, cy:int, rx:int, ry:int;
			cx = int(px / tileWidth) * tileWidth + tileWidth/2;	//计算出当前X所在的以tileWidth为宽的矩形的中心的X坐标
			cy = int(py / tileHeight) * tileHeight + tileHeight/2;//计算出当前Y所在的以tileHeight为高的矩形的中心的Y坐标
			
			rx = (px - cx) * tileHeight/2;
			ry = (py - cy) * tileWidth/2;
			
			if (Math.abs(rx)+Math.abs(ry) <= tileWidth * tileHeight/4)
			{
				//xtile = int(pixelPoint.x / tileWidth) * 2;
				xtile = int(px / tileWidth);
				ytile = int(py / tileHeight) * 2;
			}
			else
			{
				px = px - tileWidth/2;
				//xtile = int(pixelPoint.x / tileWidth) * 2 + 1;
				xtile = int(px / tileWidth) + 1;
				
				py = py - tileHeight/2;
				ytile = int(py / tileHeight) * 2 + 1;
			}
			
			return new Point(xtile - (ytile&1), ytile);
		}
		
		/**
		 * 根据逻辑坐标得到直角坐标	
		 * */
		public  function getDirectPoint(logic:Point,row:int):Point
		{
			/**
			 * 直角坐标点
			 * */
			var dPoint:Point = new Point();
			if(logic.y & 1){
				dPoint.x = Math.floor(( logic.x - logic.y / 2 ) + 1 + (row-1)/2);
			}else{
				dPoint.x = ( logic.x - logic.y / 2 ) + Math.ceil((row-1)/2);
			}
			dPoint.y = Math.floor(( logic.y / 2 ) + logic.x + ( logic.y & 1 ));
			return dPoint;
		}
		
		
		/**
		 * 根据网格坐标取得像素素坐标	
		 * */
		public  function getPixelPoint(tileWidth:int, tileHeight:int, tx:int, ty:int):Point
		{
			/**
			 * 偶数行tile中心	
			 * */
			var tileCenter:int = (tx * tileWidth) + tileWidth/2;
			/**
			 * x象素  如果为奇数行加半个宽	
			 * */
			var xPixel:int = tileCenter + (ty&1) * tileWidth/2;
			
			/**
			 * y象素	
			 * */
			var yPixel:int = (ty + 1) * tileHeight/2;
			
			return new Point(xPixel, yPixel);
		}
		
		/**
		 * 初始化游戏信息 
		 * @param xml
		 * 
		 */		
		public function initMapData(xml :XML):void
		{
			if(!xml)
			{
				trace("at MapManager initMapData xml is null");
				return;
			}
			for each(var item :XML in xml.map.mapData)
			{
				var mapData :MapData = new MapData();
				mapData.mapID = item.@mapID;
				mapData.mapName = item.@mapName;
				mapData.mapWidth = item.@mapWidth;
				mapData.mapHeight = item.@mapHeight;
				mapData.mapRows = item.@mapRows;
				mapData.mapCols = item.@mapCols;
				mapData.mapTileWidth = item.@mapTileWidth;
				mapData.mapTileHeight = item.@mapTileHeight;
				mapData.mapWalkGapWidth = item.@mapWalkGapWidth;
				mapData.mapWalkGapHeight = item.@mapWalkGapHeight;
				mapData.mapTileRows = item.@mapTileRows;
				mapData.mapTileCols = item.@mapTileCols;
				mapData.playerBornPoint = string2Point(item.@playerBornPoint);
				mapData.exitsDataList = ExitsData.createExitsDataList(item.exitsData);
				mapData.npcDataList = NPCData.createNPCDataList(item.npcData);
				mapData.monsterDataList = MonsterData.createMonsterDataList(item.monsterData);
				mapData.mapWalkAry = string2Array(item.walk,item.@mapTileRows,item.@mapTileCols);
				mapData.mapVisbleAry = string2Array(item.visble,item.@mapTileRows,item.@mapTileCols);
				mapData.lastMapID = item.@lastMapID;
				mapData.nextMapID = item.@nextMapID;
				this.mapDataList.push(mapData);
			}
			
			
			if(this.mapDataList.length > 0)
			{
				var npcIDList :Array = RoleManager.instance.npcIDList;
				var monsterIDList :Array = RoleManager.instance.monsterIDList;
				for each(var md :MapData in this.mapDataList)
				{
					if(md)
					{
						//初始化游戏xml中所有NPC的ID数据
						if(md.monsterDataList && md.monsterDataList.length > 0)
						{
							for each(var npcData :NPCData in md.npcDataList)
							{
								npcIDList.push(npcData.npcID);
							}
						}
						//初始化所有传送点的数据
						if(md.exitsDataList && md.exitsDataList.length > 0)
						{
							for each(var exitData :ExitsData in md.exitsDataList)
							{
								this.allExitDataList.push(exitData);
							}
						}
						
						//初始化游戏xml中所有怪物ID的数据
						if(md.monsterDataList && md.monsterDataList.length > 0)
						{
							for each(var monsterData :MonsterData in md.monsterDataList)
							{
								monsterIDList.push(monsterData.monsterID);
							}
						}
					}
				}
			}
			
			

			
		}
		/**
		 * 用行走数组转换成寻路用的节点数据 
		 * @param mapWalkAry
		 * @return 
		 * 
		 */		
		public function ary2WalkGrid(mapWalkAry:Array):NodeGrid 
		{
			var grid:NodeGrid = new NodeGrid(mapWalkAry[0].length, mapWalkAry.length);
			for (var col : uint = 0;col < grid.numCols;col++) 
			{
				for (var row : uint = 0;row < grid.numRows;row++) 
				{
					var node : Node = grid.getNode(col, row);
					node.walkable = !mapWalkAry[row][col];
				}
			}
			return grid;
		}
		
		/**
		 * 字符串转point 
		 * @param str
		 * @return 
		 * 
		 */		
		public function string2Point(str :String):Point
		{
			var p :Point;
			if(str)
			{
				var ary :Array = str.split(",");
				if(ary.length >= 2)
				{
					var px :int = int(ary[0]);
					var py :int = int(ary[1]);
					p = new Point(px,py);
				}
			}else
			{
				trace("at MapDataManager string2Point str null");
			}
			if(!p)
			{
				trace("at MapDataManager string2Point p null");
			}
			return p;
		}
		/**
		 * 字符串转point数组 
		 * @param str
		 * @return 
		 * 
		 */		
		public function string2PointAry(str :String):Array
		{
			var result :Array = [];
			if(str)
			{
				var ary :Array = str.split(",");
				if(ary.length >= 2)
				{
					while(ary.length > 0)
					{
						var px :int = ary.shift();
						var py :int = ary.shift();
						var p :Point = new Point(px,py);
						result.push(p);
					}
				}
			}else
			{
				trace("at MapDataManager string2PointAry str null");
			}
			if(result.length == 0)
			{
				trace("at MapDataManager string2PointAry result null");
			}
			return result;
		}
		/**
		 * 地图字符串转数组 
		 * @param str
		 * @return 
		 * 
		 */		
		public function string2Array(str :String,rows :int,cols :int):Array
		{
			var result :Array = [];
			if(str)
			{
				var arr:Array  = str.split(",");
				var index:uint = 0;
				for(var i:uint = 0 ; i < rows;i++)
				{
					var tempArr:Array = new Array();
					for(var j:uint = 0 ; j < cols; j++)
					{
						var boolean :Boolean = arr[index] == "1" ? true : false;
						tempArr.push(boolean);
						index++;
					}
					result.push(tempArr);
				}
				return result;
				
			}else
			{
				trace("at MapDataManager string2Array str null");
			}
			
			if(result.length == 0)
			{
				trace("at MapDataManager string2Array result null");
			}
			
			return result;
		}
		/**
		 * 角色动作数组转换 
		 * @param str
		 * @return 
		 * 
		 */		
		public function string2ActionAry(str :String):Array
		{
			var result :Array;
			//角色有多个动作
			if(str.indexOf(",") != -1)
			{
				result = str.split(",");
			}else   //角色只有单个动作
			{
				result = [str];
			}
			return result;
		}

		
		private function get player():MapPlayer
		{
			var gameLayer :GameLayer = LayerManager.instance.getLayer(GameLayer.NAME) as GameLayer;
			
			return gameLayer.player;
		}

	}
}

class PrivateClass{}